1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.google.common.collect;
18
19 import static com.google.common.base.Preconditions.checkNotNull;
20
21 import com.google.common.annotations.Beta;
22 import com.google.common.annotations.GwtCompatible;
23
24 import java.util.ArrayDeque;
25 import java.util.Deque;
26 import java.util.Iterator;
27 import java.util.Queue;
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 @Beta
53 @GwtCompatible(emulated = true)
54 public abstract class TreeTraverser<T> {
55
56
57
58
59
60 public abstract Iterable<T> children(T root);
61
62
63
64
65
66
67
68
69 public final FluentIterable<T> preOrderTraversal(final T root) {
70 checkNotNull(root);
71 return new FluentIterable<T>() {
72 @Override
73 public UnmodifiableIterator<T> iterator() {
74 return preOrderIterator(root);
75 }
76 };
77 }
78
79
80 UnmodifiableIterator<T> preOrderIterator(T root) {
81 return new PreOrderIterator(root);
82 }
83
84 private final class PreOrderIterator extends UnmodifiableIterator<T> {
85 private final Deque<Iterator<T>> stack;
86
87 PreOrderIterator(T root) {
88 this.stack = new ArrayDeque<Iterator<T>>();
89 stack.addLast(Iterators.singletonIterator(checkNotNull(root)));
90 }
91
92 @Override
93 public boolean hasNext() {
94 return !stack.isEmpty();
95 }
96
97 @Override
98 public T next() {
99 Iterator<T> itr = stack.getLast();
100 T result = checkNotNull(itr.next());
101 if (!itr.hasNext()) {
102 stack.removeLast();
103 }
104 Iterator<T> childItr = children(result).iterator();
105 if (childItr.hasNext()) {
106 stack.addLast(childItr);
107 }
108 return result;
109 }
110 }
111
112
113
114
115
116
117
118
119 public final FluentIterable<T> postOrderTraversal(final T root) {
120 checkNotNull(root);
121 return new FluentIterable<T>() {
122 @Override
123 public UnmodifiableIterator<T> iterator() {
124 return postOrderIterator(root);
125 }
126 };
127 }
128
129
130 UnmodifiableIterator<T> postOrderIterator(T root) {
131 return new PostOrderIterator(root);
132 }
133
134 private static final class PostOrderNode<T> {
135 final T root;
136 final Iterator<T> childIterator;
137
138 PostOrderNode(T root, Iterator<T> childIterator) {
139 this.root = checkNotNull(root);
140 this.childIterator = checkNotNull(childIterator);
141 }
142 }
143
144 private final class PostOrderIterator extends AbstractIterator<T> {
145 private final ArrayDeque<PostOrderNode<T>> stack;
146
147 PostOrderIterator(T root) {
148 this.stack = new ArrayDeque<PostOrderNode<T>>();
149 stack.addLast(expand(root));
150 }
151
152 @Override
153 protected T computeNext() {
154 while (!stack.isEmpty()) {
155 PostOrderNode<T> top = stack.getLast();
156 if (top.childIterator.hasNext()) {
157 T child = top.childIterator.next();
158 stack.addLast(expand(child));
159 } else {
160 stack.removeLast();
161 return top.root;
162 }
163 }
164 return endOfData();
165 }
166
167 private PostOrderNode<T> expand(T t) {
168 return new PostOrderNode<T>(t, children(t).iterator());
169 }
170 }
171
172
173
174
175
176
177
178
179 public final FluentIterable<T> breadthFirstTraversal(final T root) {
180 checkNotNull(root);
181 return new FluentIterable<T>() {
182 @Override
183 public UnmodifiableIterator<T> iterator() {
184 return new BreadthFirstIterator(root);
185 }
186 };
187 }
188
189 private final class BreadthFirstIterator extends UnmodifiableIterator<T>
190 implements PeekingIterator<T> {
191 private final Queue<T> queue;
192
193 BreadthFirstIterator(T root) {
194 this.queue = new ArrayDeque<T>();
195 queue.add(root);
196 }
197
198 @Override
199 public boolean hasNext() {
200 return !queue.isEmpty();
201 }
202
203 @Override
204 public T peek() {
205 return queue.element();
206 }
207
208 @Override
209 public T next() {
210 T result = queue.remove();
211 Iterables.addAll(queue, children(result));
212 return result;
213 }
214 }
215 }